// 版权所有2009年围棋作者。版权所有。
// 此源代码的使用受BSD样式的约束
// 可以在许可证文件中找到的许可证。

package gob

import (
	"encoding"
	"errors"
	"fmt"
	"os"
	"reflect"
	"sync"
	"sync/atomic"
	"unicode"
	"unicode/utf8"
)

// userTypeInfo存储与用户提交的类型相关的信息
// 到包裹里去。它只计算一次，并存储在反射键控的地图中
// 类型
type userTypeInfo struct {
	user        reflect.Type // 用户交给我们的类型
	base        reflect.Type // 所有间接操作之后的基类型
	indir       int          // 到达基类型的间接数
	externalEnc int          // xGob、xBinary或xText
	externalDec int          // xGob、xBinary或xText
	encIndir    int8         // 到达接收器类型的间接次数；可能是负面的
	decIndir    int8         // 到达接收器类型的间接次数；可能是负面的
}

// 外部编码位
const (
	xGob    = 1 + iota // GobEncoder或GobDecoder
	xBinary            // encoding.BinaryMarshaler或encoding.BinaryUnmarshaler
	xText              // encoding.TextMarshaler或encoding.TextUnmarshaler
)

var userTypeCache sync.Map // 映射[reflect.Type]*用户类型信息

// validType返回并保存与用户提供的rt类型关联的信息。
// 如果用户类型无效，err将为非nil。当错误处理程序
// 没有设置。
func validUserType(rt reflect.Type) (*userTypeInfo, error) {
	if ui, ok := userTypeCache.Load(rt); ok {
		return ui.(*userTypeInfo), nil
	}

	// 构造一个新的userTypeInfo并自动将其添加到userTypeCache。
	// 如果我们输掉比赛，我们会浪费一点CPU，制造一点垃圾
	// 但仍然返回现有值。

	ut := new(userTypeInfo)
	ut.base = rt
	ut.user = rt
	// 仅仅是指针循环的类型（例如T*T类型）不能
	// 以GOB表示，需要一些具体的数据。我们使用
	// 来自Knuth的循环检测算法，第2卷，第3.1节，Ex 6，
	// 第539-540页。当我们逐步执行间接操作时，在
	// 半速。如果他们相遇，就会有一个循环。
	slowpoke := ut.base // 步行速度只有ut.base的一半
	for {
		pt := ut.base
		if pt.Kind() != reflect.Ptr {
			break
		}
		ut.base = pt.Elem()
		if ut.base == slowpoke { // ut.基础搭接慢行程
			// 递归指针类型。
			return nil, errors.New("can't represent recursive pointer type " + ut.base.String())
		}
		if ut.indir%2 == 0 {
			slowpoke = slowpoke.Elem()
		}
		ut.indir++
	}

	if ok, indir := implementsInterface(ut.user, gobEncoderInterfaceType); ok {
		ut.externalEnc, ut.encIndir = xGob, indir
	} else if ok, indir := implementsInterface(ut.user, binaryMarshalerInterfaceType); ok {
		ut.externalEnc, ut.encIndir = xBinary, indir
	}

	// 注意（rsc）：希望在此处允许MarshalText，但会导致不兼容
	// 使用net.IP的旧编码。见golang.org/issue/6760。
	// }否则，如果确定，indir:=implementsInterface（ut.user，textMarshalerInterfaceType）；嗯{
	// ut.externalEnc，ut.encIndir=xText，indir
	// }

	if ok, indir := implementsInterface(ut.user, gobDecoderInterfaceType); ok {
		ut.externalDec, ut.decIndir = xGob, indir
	} else if ok, indir := implementsInterface(ut.user, binaryUnmarshalerInterfaceType); ok {
		ut.externalDec, ut.decIndir = xBinary, indir
	}

	// 见上文注。
	// }否则，如果确定，indir:=implementsInterface（ut.user，textUnmarshalerInterface类型）；嗯{
	// ut.externalDec，ut.decIndir=xText，indir
	// }

	ui, _ := userTypeCache.LoadOrStore(rt, ut)
	return ui.(*userTypeInfo), nil
}

var (
	gobEncoderInterfaceType        = reflect.TypeOf((*GobEncoder)(nil)).Elem()
	gobDecoderInterfaceType        = reflect.TypeOf((*GobDecoder)(nil)).Elem()
	binaryMarshalerInterfaceType   = reflect.TypeOf((*encoding.BinaryMarshaler)(nil)).Elem()
	binaryUnmarshalerInterfaceType = reflect.TypeOf((*encoding.BinaryUnmarshaler)(nil)).Elem()
	textMarshalerInterfaceType     = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
	textUnmarshalerInterfaceType   = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
)

// implementsInterface报告类型是否实现
// gobEncoder/gobDecoder接口。
// 它还返回到达目标所需的间接数
// 实施
func implementsInterface(typ, gobEncDecType reflect.Type) (success bool, indir int8) {
	if typ == nil {
		return
	}
	rt := typ
	// 类型可能是指针，我们需要保留
	// 在找到实现之前取消对基类型的引用。
	for {
		if rt.Implements(gobEncDecType) {
			return true, indir
		}
		if p := rt; p.Kind() == reflect.Ptr {
			indir++
			if indir > 100 { // 疯狂的间接数
				return false, 0
			}
			rt = p.Elem()
			continue
		}
		break
	}
	// 现在还不走运，但是如果这是一个基类型（非指针），指针可能满足以下条件。
	if typ.Kind() != reflect.Ptr {
		// 不是指针，但指针是否工作？
		if reflect.PtrTo(typ).Implements(gobEncDecType) {
			return true, -1
		}
	}
	return false, 0
}

// userType返回并保存与用户提供的类型rt关联的信息。
// 如果用户类型无效，则调用error。
func userType(rt reflect.Type) *userTypeInfo {
	ut, err := validUserType(rt)
	if err != nil {
		error_(err)
	}
	return ut
}

// typeId将gob类型表示为可以在线路上传递的整数。
// 在内部，TypeID用作映射的键，以恢复基础类型信息。
type typeId int32

var nextId typeId       // 对于我们构建的每个新类型，都会增加
var typeLock sync.Mutex // 在生成类型时设置
const firstUserId = 64  // 授予用户的最低id号

type gobType interface {
	id() typeId
	setId(id typeId)
	name() string
	string() string // 不公开；仅用于调试
	safeString(seen map[typeId]bool) string
}

var types = make(map[reflect.Type]gobType)
var idToType = make(map[typeId]gobType)
var builtinIdToType map[typeId]gobType // 建立内置项后在init（）中设置

func setTypeId(typ gobType) {
	// 在构建递归类型时，可能有人比我们先到达那里。
	if typ.id() != 0 {
		return
	}
	nextId++
	typ.setId(nextId)
	idToType[nextId] = typ
}

func (t typeId) gobType() gobType {
	if t == 0 {
		return nil
	}
	return idToType[t]
}

// string返回与typeId关联的类型的字符串表示形式。
func (t typeId) string() string {
	if t.gobType() == nil {
		return "<nil>"
	}
	return t.gobType().string()
}

// Name返回与typeId关联的类型的名称。
func (t typeId) name() string {
	if t.gobType() == nil {
		return "<nil>"
	}
	return t.gobType().name()
}

// CommonType保存所有类型的元素。
// 它是一个历史文物，为二进制兼容而保存并导出
// 仅用于包的类型描述符编码。它是
// 不供客户直接使用。
type CommonType struct {
	Name string
	Id   typeId
}

func (t *CommonType) id() typeId { return t.Id }

func (t *CommonType) setId(id typeId) { t.Id = id }

func (t *CommonType) string() string { return t.Name }

func (t *CommonType) safeString(seen map[typeId]bool) string {
	return t.Name
}

func (t *CommonType) name() string { return t.Name }

// 创建并检查预定义类型
// tBytes的字符串是“bytes”而不是“[]byte”，以表示其特殊性。

var (
	// 初始化期间需要的原始类型。
	// 始终作为指针传递，因此接口{}类型
	// 通过而不失去它的接口。
	tBool      = bootstrapType("bool", (*bool)(nil), 1)
	tInt       = bootstrapType("int", (*int)(nil), 2)
	tUint      = bootstrapType("uint", (*uint)(nil), 3)
	tFloat     = bootstrapType("float", (*float64)(nil), 4)
	tBytes     = bootstrapType("bytes", (*[]byte)(nil), 5)
	tString    = bootstrapType("string", (*string)(nil), 6)
	tComplex   = bootstrapType("complex", (*complex128)(nil), 7)
	tInterface = bootstrapType("interface", (*interface{})(nil), 8)
	// 为兼容扩展保留一些ID
	tReserved7 = bootstrapType("_reserved1", (*struct{ r7 int })(nil), 9)
	tReserved6 = bootstrapType("_reserved1", (*struct{ r6 int })(nil), 10)
	tReserved5 = bootstrapType("_reserved1", (*struct{ r5 int })(nil), 11)
	tReserved4 = bootstrapType("_reserved1", (*struct{ r4 int })(nil), 12)
	tReserved3 = bootstrapType("_reserved1", (*struct{ r3 int })(nil), 13)
	tReserved2 = bootstrapType("_reserved1", (*struct{ r2 int })(nil), 14)
	tReserved1 = bootstrapType("_reserved1", (*struct{ r1 int })(nil), 15)
)

// 预定义，因为解码器需要它
var tWireType = mustGetTypeInfo(reflect.TypeOf(wireType{})).id
var wireTypeUserInfo *userTypeInfo // 用户类型信息（*wireType）

func init() {
	// 一些神奇的数字，以确保没有意外。
	checkId(16, tWireType)
	checkId(17, mustGetTypeInfo(reflect.TypeOf(arrayType{})).id)
	checkId(18, mustGetTypeInfo(reflect.TypeOf(CommonType{})).id)
	checkId(19, mustGetTypeInfo(reflect.TypeOf(sliceType{})).id)
	checkId(20, mustGetTypeInfo(reflect.TypeOf(structType{})).id)
	checkId(21, mustGetTypeInfo(reflect.TypeOf(fieldType{})).id)
	checkId(23, mustGetTypeInfo(reflect.TypeOf(mapType{})).id)

	builtinIdToType = make(map[typeId]gobType)
	for k, v := range idToType {
		builtinIdToType[k] = v
	}

	// 向上移动id空间，以允许在预定义的世界中增长
	// 不破坏现有文件。
	if nextId > firstUserId {
		panic(fmt.Sprintln("nextId too large:", nextId))
	}
	nextId = firstUserId
	registerBasics()
	wireTypeUserInfo = userType(reflect.TypeOf((*wireType)(nil)))
}

// 数组类型
type arrayType struct {
	CommonType
	Elem typeId
	Len  int
}

func newArrayType(name string) *arrayType {
	a := &arrayType{CommonType{Name: name}, 0, 0}
	return a
}

func (a *arrayType) init(elem gobType, len int) {
	// 在评估元素之前设置类型id，以防它是我们自己的。
	setTypeId(a)
	a.Elem = elem.id()
	a.Len = len
}

func (a *arrayType) safeString(seen map[typeId]bool) string {
	if seen[a.Id] {
		return a.Name
	}
	seen[a.Id] = true
	return fmt.Sprintf("[%d]%s", a.Len, a.Elem.gobType().safeString(seen))
}

func (a *arrayType) string() string { return a.safeString(make(map[typeId]bool)) }

// GobEncoder类型（实现GobEncoder接口的东西）
type gobEncoderType struct {
	CommonType
}

func newGobEncoderType(name string) *gobEncoderType {
	g := &gobEncoderType{CommonType{Name: name}}
	setTypeId(g)
	return g
}

func (g *gobEncoderType) safeString(seen map[typeId]bool) string {
	return g.Name
}

func (g *gobEncoderType) string() string { return g.Name }

// 地图类型
type mapType struct {
	CommonType
	Key  typeId
	Elem typeId
}

func newMapType(name string) *mapType {
	m := &mapType{CommonType{Name: name}, 0, 0}
	return m
}

func (m *mapType) init(key, elem gobType) {
	// 在评估元素之前设置类型id，以防它是我们自己的。
	setTypeId(m)
	m.Key = key.id()
	m.Elem = elem.id()
}

func (m *mapType) safeString(seen map[typeId]bool) string {
	if seen[m.Id] {
		return m.Name
	}
	seen[m.Id] = true
	key := m.Key.gobType().safeString(seen)
	elem := m.Elem.gobType().safeString(seen)
	return fmt.Sprintf("map[%s]%s", key, elem)
}

func (m *mapType) string() string { return m.safeString(make(map[typeId]bool)) }

// 切片类型
type sliceType struct {
	CommonType
	Elem typeId
}

func newSliceType(name string) *sliceType {
	s := &sliceType{CommonType{Name: name}, 0}
	return s
}

func (s *sliceType) init(elem gobType) {
	// 在评估元素之前设置类型id，以防它是我们自己的。
	setTypeId(s)
	// 请参阅newTypeObject中有关ID的注释。只有切片和
	// 结构具有相互递归性。
	if elem.id() == 0 {
		setTypeId(elem)
	}
	s.Elem = elem.id()
}

func (s *sliceType) safeString(seen map[typeId]bool) string {
	if seen[s.Id] {
		return s.Name
	}
	seen[s.Id] = true
	return fmt.Sprintf("[]%s", s.Elem.gobType().safeString(seen))
}

func (s *sliceType) string() string { return s.safeString(make(map[typeId]bool)) }

// 结构类型
type fieldType struct {
	Name string
	Id   typeId
}

type structType struct {
	CommonType
	Field []*fieldType
}

func (s *structType) safeString(seen map[typeId]bool) string {
	if s == nil {
		return "<nil>"
	}
	if _, ok := seen[s.Id]; ok {
		return s.Name
	}
	seen[s.Id] = true
	str := s.Name + " = struct { "
	for _, f := range s.Field {
		str += fmt.Sprintf("%s %s; ", f.Name, f.Id.gobType().safeString(seen))
	}
	str += "}"
	return str
}

func (s *structType) string() string { return s.safeString(make(map[typeId]bool)) }

func newStructType(name string) *structType {
	s := &structType{CommonType{Name: name}, nil}
	// 出于历史原因，我们在此处设置id，而不是init。
	// 有关详细信息，请参见newTypeObject中的注释。
	setTypeId(s)
	return s
}

// newTypeObject为反射类型rt分配一个类型。
// 除非ut表示GobEncoder，否则rt应该是基类型
// 当然可以。
// 这仅从编码端调用。解码端
// 仅通过TypeID和userTypeInfos工作。
func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, error) {
	// 这种类型是否实现了GobEncoder？
	if ut.externalEnc != 0 {
		return newGobEncoderType(name), nil
	}
	var err error
	var type0, type1 gobType
	defer func() {
		if err != nil {
			delete(types, rt)
		}
	}()
	// 在子类型之前安装顶级类型（例如，在子类型之前安装struct
	// 字段），以便可以安全地构造递归类型。
	switch t := rt; t.Kind() {
	// 所有基本类型都很简单：它们是预定义的。
	case reflect.Bool:
		return tBool.gobType(), nil

	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return tInt.gobType(), nil

	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return tUint.gobType(), nil

	case reflect.Float32, reflect.Float64:
		return tFloat.gobType(), nil

	case reflect.Complex64, reflect.Complex128:
		return tComplex.gobType(), nil

	case reflect.String:
		return tString.gobType(), nil

	case reflect.Interface:
		return tInterface.gobType(), nil

	case reflect.Array:
		at := newArrayType(name)
		types[rt] = at
		type0, err = getBaseType("", t.Elem())
		if err != nil {
			return nil, err
		}
		// 历史旁白：
		// 对于数组、映射和切片，我们在元素之后设置类型id
		// 都是建造的。这是为了保留类型id分配后的顺序
		// 为处理递归类型而进行的修复，它更改了中的顺序
		// 构建了哪些类型。以这种方式延迟设置将保留
		// 类型ID，同时允许描述递归类型。结构，
		// 我们已经正确地处理了递归，所以
		// 在字段的顶级id之前分配顶级id。
		at.init(type0, t.Len())
		return at, nil

	case reflect.Map:
		mt := newMapType(name)
		types[rt] = mt
		type0, err = getBaseType("", t.Key())
		if err != nil {
			return nil, err
		}
		type1, err = getBaseType("", t.Elem())
		if err != nil {
			return nil, err
		}
		mt.init(type0, type1)
		return mt, nil

	case reflect.Slice:
		// []字节==[]uint8是一种特殊情况
		if t.Elem().Kind() == reflect.Uint8 {
			return tBytes.gobType(), nil
		}
		st := newSliceType(name)
		types[rt] = st
		type0, err = getBaseType(t.Elem().Name(), t.Elem())
		if err != nil {
			return nil, err
		}
		st.init(type0)
		return st, nil

	case reflect.Struct:
		st := newStructType(name)
		types[rt] = st
		idToType[st.id()] = st
		for i := 0; i < t.NumField(); i++ {
			f := t.Field(i)
			if !isSent(&f) {
				continue
			}
			typ := userType(f.Type).base
			tname := typ.Name()
			if tname == "" {
				t := userType(f.Type).base
				tname = t.String()
			}
			gt, err := getBaseType(tname, f.Type)
			if err != nil {
				return nil, err
			}
			// 一些相互递归的类型可能导致我们在
			// 仍在定义元素。在这里修复元素类型id。
			// 我们可以通过在开始时设置id来更简洁地完成这项工作
			// 构建每种类型，但这会破坏二进制兼容性。
			if gt.id() == 0 {
				setTypeId(gt)
			}
			st.Field = append(st.Field, &fieldType{f.Name, gt.id()})
		}
		return st, nil

	default:
		return nil, errors.New("gob NewTypeObject can't handle type: " + rt.String())
	}
}

// isExported报告这是否是导出的大写名称。
func isExported(name string) bool {
	rune, _ := utf8.DecodeRuneInString(name)
	return unicode.IsUpper(rune)
}

// ISENT报告是否要传输此结构字段。
// 仅在导出时传输，而不是chan或func字段
// 或指向chan或func的指针。
func isSent(field *reflect.StructField) bool {
	if !isExported(field.Name) {
		return false
	}
	// 如果字段是chan或func或其指针，则不要发送它。
	// 也就是说，将其视为未报告的字段。
	typ := field.Type
	for typ.Kind() == reflect.Ptr {
		typ = typ.Elem()
	}
	if typ.Kind() == reflect.Chan || typ.Kind() == reflect.Func {
		return false
	}
	return true
}

// getBaseType返回描述给定reflect.type的基类型的Gob类型。
// 必须保持打字锁。
func getBaseType(name string, rt reflect.Type) (gobType, error) {
	ut := userType(rt)
	return getType(name, ut, ut.base)
}

// getType返回描述给定reflect.type的Gob类型。
// 应仅在处理编码器/解码器时调用，
// 这可能是指针。所有其他类型都通过
// 基类型，而不是指针。
// 必须保持打字锁。
func getType(name string, ut *userTypeInfo, rt reflect.Type) (gobType, error) {
	typ, present := types[rt]
	if present {
		return typ, nil
	}
	typ, err := newTypeObject(name, ut, rt)
	if err == nil {
		types[rt] = typ
	}
	return typ, err
}

func checkId(want, got typeId) {
	if want != got {
		fmt.Fprintf(os.Stderr, "checkId: %d should be %d\n", int(got), int(want))
		panic("bootstrap type wrong id: " + got.name() + " " + got.string() + " not " + want.string())
	}
}

// 用于构建基本类型；仅从init（）调用。来袭的
// 接口始终引用指针。
func bootstrapType(name string, e interface{}, expect typeId) typeId {
	rt := reflect.TypeOf(e).Elem()
	_, present := types[rt]
	if present {
		panic("bootstrap type already present: " + name + ", " + rt.String())
	}
	typ := &CommonType{Name: name}
	types[rt] = typ
	setTypeId(typ)
	checkId(expect, nextId)
	userType(rt) // 不如现在就把它缓存起来
	return nextId
}

// 表示我们发送和接收的有关此类型的信息。
// 我们发送的每个值前面都有它的类型定义：一个编码的int。
// 但是，在我们第一次发送值时，我们首先发送该对
// （-id，wireType）。
// 出于引导的目的，我们假设接收者知道如何引导
// 解码有线类型；这正是此处解释的wireType结构
// 使用gob规则发送结构，但我们假设
// 已知wireType和structType等的ID。相关条款
// 是内置的encode.go的init（）函数。
// 要保持二进制兼容性，如果扩展此类型，请始终
// 新的田地是最后的。
type wireType struct {
	ArrayT           *arrayType
	SliceT           *sliceType
	StructT          *structType
	MapT             *mapType
	GobEncoderT      *gobEncoderType
	BinaryMarshalerT *gobEncoderType
	TextMarshalerT   *gobEncoderType
}

func (w *wireType) string() string {
	const unknown = "unknown type"
	if w == nil {
		return unknown
	}
	switch {
	case w.ArrayT != nil:
		return w.ArrayT.Name
	case w.SliceT != nil:
		return w.SliceT.Name
	case w.StructT != nil:
		return w.StructT.Name
	case w.MapT != nil:
		return w.MapT.Name
	case w.GobEncoderT != nil:
		return w.GobEncoderT.Name
	case w.BinaryMarshalerT != nil:
		return w.BinaryMarshalerT.Name
	case w.TextMarshalerT != nil:
		return w.TextMarshalerT.Name
	}
	return unknown
}

type typeInfo struct {
	id      typeId
	encInit sync.Mutex   // 保护编码器的创建
	encoder atomic.Value // *恩琴
	wire    *wireType
}

// typeInfoMap是指向map[reflect.Type]*typeInfo的原子指针。
// 这是一份更新的书面副本。读者只需进行原子加载
// 以获取地图的当前版本。作者制作了一份完整的
// 映射并自动更新指针以指向新映射。
// 在严重的读争用情况下，这比映射要快得多
// 由互斥锁保护。
var typeInfoMap atomic.Value

func lookupTypeInfo(rt reflect.Type) *typeInfo {
	m, _ := typeInfoMap.Load().(map[reflect.Type]*typeInfo)
	return m[rt]
}

func getTypeInfo(ut *userTypeInfo) (*typeInfo, error) {
	rt := ut.base
	if ut.externalEnc != 0 {
		// 我们需要的是用户类型，而不是基类型。
		rt = ut.user
	}
	if info := lookupTypeInfo(rt); info != nil {
		return info, nil
	}
	return buildTypeInfo(ut, rt)
}

// buildTypeInfo构造类型的类型信息
// 并将其存储在类型信息映射中。
func buildTypeInfo(ut *userTypeInfo, rt reflect.Type) (*typeInfo, error) {
	typeLock.Lock()
	defer typeLock.Unlock()

	if info := lookupTypeInfo(rt); info != nil {
		return info, nil
	}

	gt, err := getBaseType(rt.Name(), rt)
	if err != nil {
		return nil, err
	}
	info := &typeInfo{id: gt.id()}

	if ut.externalEnc != 0 {
		userType, err := getType(rt.Name(), ut, rt)
		if err != nil {
			return nil, err
		}
		gt := userType.id().gobType().(*gobEncoderType)
		switch ut.externalEnc {
		case xGob:
			info.wire = &wireType{GobEncoderT: gt}
		case xBinary:
			info.wire = &wireType{BinaryMarshalerT: gt}
		case xText:
			info.wire = &wireType{TextMarshalerT: gt}
		}
		rt = ut.user
	} else {
		t := info.id.gobType()
		switch typ := rt; typ.Kind() {
		case reflect.Array:
			info.wire = &wireType{ArrayT: t.(*arrayType)}
		case reflect.Map:
			info.wire = &wireType{MapT: t.(*mapType)}
		case reflect.Slice:
			// []字节==[]uint8是一个单独处理的特殊情况
			if typ.Elem().Kind() != reflect.Uint8 {
				info.wire = &wireType{SliceT: t.(*sliceType)}
			}
		case reflect.Struct:
			info.wire = &wireType{StructT: t.(*structType)}
		}
	}

	// 使用旧内容和新条目创建新地图。
	newm := make(map[reflect.Type]*typeInfo)
	m, _ := typeInfoMap.Load().(map[reflect.Type]*typeInfo)
	for k, v := range m {
		newm[k] = v
	}
	newm[rt] = info
	typeInfoMap.Store(newm)
	return info, nil
}

// 只有在恐慌可以接受且出乎意料时才调用。
func mustGetTypeInfo(rt reflect.Type) *typeInfo {
	t, err := getTypeInfo(userType(rt))
	if err != nil {
		panic("getTypeInfo: " + err.Error())
	}
	return t
}

// GobEncoder是描述数据的接口，它提供自己的
// 对传输到解码器的值进行编码的表示。
// 实现GobEncoder和GobDecoder的类型已完成
// 控制其数据的表示，因此可能
// 包含私有字段、通道和函数等内容，
// 通常不会在采空区流中传播。
// None
// 注：由于采空区可永久储存，因此设计良好
// 确保GobEncoder使用的编码与
// 软件发展。例如，它可能对GobEncode有意义
// 在编码中包含版本号。
type GobEncoder interface {
	// GobEncode返回一个字节片，表示
	// 用于传输到解码器的接收器，通常是相同的
	// 混凝土类型。
	GobEncode() ([]byte, error)
}

// GobDecoder是描述数据的接口，它提供自己的
// 对编码器发送的传输值进行解码的例行程序。
type GobDecoder interface {
	// GoDecode覆盖接收器，接收器必须是指针，
	// 使用由字节片表示的值，该字节片被写入
	// 通过GobEncode，通常用于相同的混凝土类型。
	GobDecode([]byte) error
}

var (
	nameToConcreteType sync.Map // map[string]reflect.Type
	concreteTypeToName sync.Map // 映射[reflect.Type]字符串
)

// RegisterName类似于Register，但使用提供的名称而不是
// 类型的默认值。
func RegisterName(name string, value interface{}) {
	if name == "" {
		// 为零保留
		panic("attempt to register empty name")
	}

	ut := userType(reflect.TypeOf(value))

	// 检查不兼容的副本。该名称必须引用
	// 相同的用户类型，反之亦然。

	// 存储用户提供的名称和类型。。。。
	if t, dup := nameToConcreteType.LoadOrStore(name, reflect.TypeOf(value)); dup && t != ut.user {
		panic(fmt.Sprintf("gob: registering duplicate types for %q: %s != %s", name, t, ut.user))
	}

	// 但是类型表中的扁平类型，因为这是解码需要的。
	if n, dup := concreteTypeToName.LoadOrStore(ut.base, name); dup && n != name {
		nameToConcreteType.Delete(name)
		panic(fmt.Sprintf("gob: registering duplicate names for %s: %q != %q", ut.user, n, name))
	}
}

// 寄存器在其下记录由该类型的值标识的类型
// 内部类型名。该名称将标识值的具体类型
// 作为接口变量发送或接收。只有将被删除的类型
// 作为接口值的实现进行传输需要注册。
// 由于只希望在初始化期间使用，如果映射
// 类型和名称之间不是双射。
func Register(value interface{}) {
	// 默认为未命名类型的打印表示形式
	rt := reflect.TypeOf(value)
	name := rt.String()

	// 但对于命名类型（或指向它们的指针），请使用导入路径进行限定（但请参见内部注释）。
	// 取消引用一个指针以查找命名类型。
	star := ""
	if rt.Name() == "" {
		if pt := rt; pt.Kind() == reflect.Ptr {
			star = "*"
			// 注意：下面的行应该是rt=pt.Elem（）以实现
			// 上面的评论声称了什么，但修复它会破坏兼容性
			// 利用现有采空区。
			// None
			// 给定以“完整/p”形式导入的p包，定义如下：
			// 包p
			// 类型T1结构{…}
			// 此表显示了gob使用的预期字符串和实际字符串
			// 命名类型：
			// None
			// 键入正确的字符串实际字符串
			// None
			// T1满/p.T1满/p.T1
			// *T1*满/p.T1*p.T1
			// None
			// 如果不中断现有的gob解码器，则无法修复丢失的完整路径。
			rt = pt
		}
	}
	if rt.Name() != "" {
		if rt.PkgPath() == "" {
			name = star + rt.Name()
		} else {
			name = star + rt.PkgPath() + "." + rt.Name()
		}
	}

	RegisterName(name, value)
}

func registerBasics() {
	Register(int(0))
	Register(int8(0))
	Register(int16(0))
	Register(int32(0))
	Register(int64(0))
	Register(uint(0))
	Register(uint8(0))
	Register(uint16(0))
	Register(uint32(0))
	Register(uint64(0))
	Register(float32(0))
	Register(float64(0))
	Register(complex64(0i))
	Register(complex128(0i))
	Register(uintptr(0))
	Register(false)
	Register("")
	Register([]byte(nil))
	Register([]int(nil))
	Register([]int8(nil))
	Register([]int16(nil))
	Register([]int32(nil))
	Register([]int64(nil))
	Register([]uint(nil))
	Register([]uint8(nil))
	Register([]uint16(nil))
	Register([]uint32(nil))
	Register([]uint64(nil))
	Register([]float32(nil))
	Register([]float64(nil))
	Register([]complex64(nil))
	Register([]complex128(nil))
	Register([]uintptr(nil))
	Register([]bool(nil))
	Register([]string(nil))
}
